package csc420groupproject;

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import javax.swing.*;

/**
 * 
 */
public class GUI extends JFrame {
    public final static String BOILERPLATE =    "\\documentclass[12pt]\n" +
                                                "\\begin{document}\n" +
                                                "\\end{document}";
    public final static String PATH = "/icons/";

    private final boolean isDebug;

    private CustomActionListener actionListener;
    private JPanel north, center;
    private Color guiTextColor = Color.BLACK;
    private Color guiForeground = Color.WHITE;
    private Color guiBackground = new Color(230, 230, 230);
    private boolean initialize;

    protected Color foreground = Color.BLACK;
    protected Color background = Color.WHITE;
    protected JTextArea compilerReturnArea, latexCodeArea;
    protected JTextField formulaField;
    protected HashMap<String, String> formulas, functions, symbolMap;
    protected HashMap <String, Integer> functionsCursorLoc;
    protected HashSet<String> helperWords;
    protected JPanel formulaMainPanel;
    protected JTabbedPane toolBarPanel;
    protected JScrollPane south;
    protected JToolBar textToolBar, mathToolBar;
    protected JFileChooser fileChooser;
    protected JButton showHideCompileAreaButton;
    protected JPopupMenu popup;
    protected JColorChooser colorChooserFore, colorChooserBack;
    protected JFrame optionsFrame;

    /**
     *
     * @param frameTitle
     */
    public GUI(String frameTitle, boolean isDebug) {
        super(frameTitle);
        this.isDebug = isDebug;
        this.actionListener = new CustomActionListener(this, isDebug);
        CustomKeyListener keyListener = new CustomKeyListener();
        this.initialize = true;

        //initialize the colorChooser stuff
        optionsFrame = new JFrame("Options");
        optionsFrame.setForeground(foreground);
        optionsFrame.setBackground(background);
        JButton colorButtonFore = new JButton("Set Foreground Color");
        colorButtonFore.addActionListener(actionListener);
        JPanel foregroundPanel = new JPanel(new BorderLayout());
        colorChooserFore = new JColorChooser();
        colorChooserFore.setBackground(background);
        colorChooserFore.setForeground(foreground);
        foregroundPanel.add(colorChooserFore, BorderLayout.CENTER);
        foregroundPanel.add(colorButtonFore, BorderLayout.SOUTH);
        JButton colorButtonBack = new JButton("Set Background Color");
        colorButtonBack.addActionListener(actionListener);
        JPanel backgroundPanel = new JPanel(new BorderLayout());
        colorChooserBack = new JColorChooser();
        colorChooserBack.setBackground(background);
        colorChooserBack.setForeground(foreground);
        backgroundPanel.add(colorChooserBack, BorderLayout.CENTER);
        backgroundPanel.add(colorButtonBack, BorderLayout.SOUTH);
        JTabbedPane colorPane = new JTabbedPane(JTabbedPane.TOP);
        colorPane.setName("colorChooser");
        colorPane.insertTab("Background", null, backgroundPanel, "Background Color", 0);
        colorPane.insertTab("ForeGround", null, foregroundPanel, "Foreground Color", 1);
        optionsFrame.add(colorPane);
        optionsFrame.setPreferredSize(new Dimension(500,400));
        optionsFrame.pack();

        this.formulas = new HashMap<String, String>();
        this.formulas.put("frac",   "\\frac{NUMERATOR}{DENOMINATOR}");
        this.formulas.put("sqrt",   "\\sqrt [NTH_ROOT]{VALUE}");
        this.formulas.put("limit",  "\\lim_{VARIABLE\\to\\VALUE}{EXPRESSION}");
        this.formulas.put("sum",    "\\sum_{LOWER}^{UPPER}{EXPRESSION}");
        this.formulas.put("int",    "\\int^UPPER_LOWER EXPRESSION\\,dx = VALUE");
        this.formulas.put("mod",    "VALUE \\equiv VALUE \\bmod{VALUE}");
        this.formulas.put("binom",  "\\binom{TOP}{BOTTOM}");
        this.formulas.put("infty",  "\\infty");

        this.functions = new HashMap<String, String>();
        this.functionsCursorLoc = new HashMap<String, Integer>();
        this.functions.put("alignLeft", "{\\raggedright\n" +
                                        "\n" +
                                        "}");
        this.functionsCursorLoc.put("alignLeft", 14);
        this.functions.put("alignCenter","{\\centering\n" +
                                        "\n" +
                                        "}");
        this.functionsCursorLoc.put("alignCenter", 12);
        this.functions.put("alignRight","{\\raggedleft\n" +
                                        "\n" +
                                        "}");
        this.functionsCursorLoc.put("alignRight", 13);
        this.functions.put("enum",      "\\begin{enumerate}\n" +
                                        "\n" +
                                        "\\end{enumerate}");
        this.functionsCursorLoc.put("enum", 18);
        this.functions.put("list",      "\\begin{itemize}\n" +
                                        "\n" +
                                        "\\end{itemize}");
        this.functionsCursorLoc.put("list", 17);
        this.functions.put("section",   "\\section {}");
        this.functionsCursorLoc.put("section", 11);
        this.functions.put("table_e",   "\\begin{tabular}{COLUMN_FORMATTING}\n" +
                                        "\\hline\n" +
                                        "\\multicolumn {#_OF_COLUMNS}{ALIGNMENT}{TITLE} \\\\\n" +
                                        "\\hline\n" +
                                        " \\\\\n" +
                                        "\\hline\n" +
                                        "\\end{tabular}");
        this.functionsCursorLoc.put("table_e", 100);
        this.functions.put("table_c",   "\\begin{tabular}{COLUMN_FORMATTING}\n" +
                                        " \\\\\n" +
                                        "\\end{tabular}");
        this.functionsCursorLoc.put("table_c", 37);
        this.functions.put("Bold",      "{\\bf TEXT}");
        this.functionsCursorLoc.put("Bold", 5);
        this.functions.put("Italic",    "{\\emph TEXT}");
        this.functionsCursorLoc.put("Italic", 7);
        this.functions.put("Underline", "{\\underline TEXT}");
        this.functionsCursorLoc.put("Underline", 12);

        this.symbolMap = new HashMap<String, String>();
        this.symbolMap.put("leq", "\\leq");
        this.symbolMap.put("geq", "\\geq");
        this.symbolMap.put("neq", "\\neq");
        this.symbolMap.put("equiv", "\\equiv");
        this.symbolMap.put("propto", "\\propto");
        this.symbolMap.put("cong", "\\cong");
        this.symbolMap.put("approx", "\\approx");
        this.symbolMap.put("times", "\\times");
        this.symbolMap.put("divide", "\\div");
        this.symbolMap.put("infinity", "\\infty");
        this.symbolMap.put("implies", "\\Rightarrow");
        this.symbolMap.put("forall", "\\forall");
        this.symbolMap.put("exists", "\\exists");
        this.symbolMap.put("empty", "\\emptyset");
        this.symbolMap.put("neg", "\\neg");
        this.symbolMap.put("subset", "\\subset");
        this.symbolMap.put("subseteq", "\\subseteq");
        this.symbolMap.put("supset", "\\supset");
        this.symbolMap.put("supseteq", "\\supseteq");
        this.symbolMap.put("in", "\\in");
        this.symbolMap.put("notin", "\\ni");
        this.symbolMap.put("inter", "\\cap");
        this.symbolMap.put("union", "\\cup");
        this.symbolMap.put("integral", "\\int");
        this.symbolMap.put("partial", "\\partial");
        
        //build the helpertext from our statically designated helper commands
        this.helperWords = new HashSet<String>();
        ArrayList<String> itr = new ArrayList(this.formulas.values());
        for (String helperText : itr) {
            String[] parsedHelperText = helperText.split("[{}\\[\\]]");
            //always start at the 2nd string, because it needs to be opened
            //meaning there will always be some garbage in front of it
            for (int placeCounter = 1; placeCounter < parsedHelperText.length;
                    placeCounter += 2) {
                this.helperWords.add(parsedHelperText[placeCounter]);
            }
        }

        if (isDebug) {
            System.out.println("Helper words:");
            Iterator<String> temp1 = this.helperWords.iterator();
            for (; temp1.hasNext();) {
                System.out.println(temp1.next());
            }
        }

        this.setLayout(new BorderLayout(2, 2));

        /***********************************************************************
         *          Menu
         **********************************************************************/
        JMenuBar menu = new JMenuBar();
        menu.setBackground(guiBackground);
        this.setJMenuBar(menu);

        this.fileChooser = new JFileChooser();

        /* File Menu */
        JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic('F');
        //new
        JMenuItem newItem = new JMenuItem("New");
        newItem.setMnemonic('N');
        newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
                InputEvent.CTRL_MASK));
        fileMenu.add(newItem);
        //open
        JMenuItem openItem = new JMenuItem("Open");
        openItem.setMnemonic('O');
        openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
                InputEvent.CTRL_MASK));
        fileMenu.add(openItem);
        //close
        JMenuItem closeItem = new JMenuItem("Close");
        closeItem.setMnemonic('C');
        closeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
                InputEvent.CTRL_MASK));
        fileMenu.add(closeItem);
        //save
        JMenuItem saveItem = new JMenuItem("Save");
        saveItem.setMnemonic('S');
        saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
                InputEvent.CTRL_MASK));
        fileMenu.add(saveItem);
        //export
        JMenuItem exportItem = new JMenuItem("Export");
        exportItem.setMnemonic('E');
        fileMenu.add(exportItem);
        //exit
        JMenuItem exitItem = new JMenuItem("Exit");
        exitItem.setMnemonic('x');
        exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
                InputEvent.CTRL_MASK));
        fileMenu.add(exitItem);
        menu.add(fileMenu);

        /* Edit Menu */
        JMenu editMenu = new JMenu("Edit");
        editMenu.setMnemonic('E');
        //undo
        JMenuItem undoItem = new JMenuItem("Undo");
        undoItem.setMnemonic('U');
        undoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z,
                InputEvent.CTRL_MASK));
        editMenu.add(undoItem);
        //redo
        JMenuItem redoItem = new JMenuItem("Redo");
        redoItem.setMnemonic('R');
        redoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y,
                InputEvent.CTRL_MASK));
        editMenu.add(redoItem);
        //
        editMenu.addSeparator();
        //preview
        JMenuItem previewItem = new JMenuItem("Preview");
        previewItem.setActionCommand("Preview");
        previewItem.setMnemonic('P');
        previewItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,
                InputEvent.CTRL_MASK + InputEvent.SHIFT_MASK));
        editMenu.add(previewItem);
        //
        editMenu.addSeparator();
        //options
        JMenuItem optionsItem = new JMenuItem("Options");
        optionsItem.setActionCommand("Options");
        optionsItem.setMnemonic('O');
        editMenu.add(optionsItem);
        menu.add(editMenu);

        /* Format menu (Hidden) */
        JMenu formatMenu = new JMenu("Format");
        formatMenu.setMnemonic('M');
        //bold
        JMenuItem boldItem = new JMenuItem("Bold");
        boldItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B,
                InputEvent.CTRL_MASK));
        formatMenu.add(boldItem);
        //italic
        JMenuItem italicItem = new JMenuItem("Italic");
        italicItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I,
                InputEvent.CTRL_MASK));
        formatMenu.add(italicItem);
        //underline
        JMenuItem underlineItem = new JMenuItem("Underline");
        underlineItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U,
                InputEvent.CTRL_MASK));
        formatMenu.add(underlineItem);
        formatMenu.setVisible(true);
        menu.add(formatMenu);

        /* Help menu */
        JMenu aboutMenu = new JMenu("Help");
        aboutMenu.setMnemonic('H');
        //about
        JMenuItem aboutItem = new JMenuItem("About");
        aboutItem.setMnemonic('A');
        aboutMenu.add(aboutItem);
        //help
        JMenuItem helpItem = new JMenuItem("Help");
        helpItem.setMnemonic('H');
        aboutMenu.add(helpItem);
        menu.add(aboutMenu);

        //set some colors and some action listeners
        this.iterateThroughContainer(menu);

        /* Popup menu */
        this.latexCodeArea = new JTextArea();
        this.popup = new JPopupMenu();
        //new section
        JMenuItem sectionPopupItem = new JMenuItem("Insert section");
        sectionPopupItem.setActionCommand("section");
        this.popup.add(sectionPopupItem);
        //new numbered list
        JMenuItem enumPopupItem = new JMenuItem("Insert numbered list");
        enumPopupItem.setActionCommand("enum");
        this.popup.add(enumPopupItem);
        //new item in list
        JMenuItem itemPopupItem = new JMenuItem("Insert item");
        itemPopupItem.setActionCommand("listItem");
        itemPopupItem.setVisible(false);
        this.popup.add(itemPopupItem);
        //new bullet list
        JMenuItem listPopupItem = new JMenuItem("Insert bullet list");
        listPopupItem.setActionCommand("list");
        this.popup.add(listPopupItem);
        //new table (cell)
        JMenuItem tablePopupItem = new JMenuItem("Insert table");
        tablePopupItem.setActionCommand("table_e");
        this.popup.add(tablePopupItem);
        //new column
        JMenuItem columnPopupItem = new JMenuItem("Insert column");
        columnPopupItem.setActionCommand("table_c");
        this.popup.add(columnPopupItem);

        this.iterateThroughContainer(this.popup);

        MouseListener popupListener = new PopupListener(this);
        this.latexCodeArea.addMouseListener(popupListener);
        /***********************************************************************
         *
         **********************************************************************/
        this.north = new JPanel(new BorderLayout(3, 1));
        this.north.setForeground(this.guiTextColor);
        this.north.setBackground(this.guiBackground);

        /***********************************************************************
         *          Toolbars
         **********************************************************************/

        /* Text Mode Toolbar */
        this.textToolBar = new JToolBar();
        this.textToolBar.setName("textToolBar");
        this.textToolBar.setFloatable(false);
        this.textToolBar.setBackground(this.guiBackground);

        //align left
        JButton alignLeftButton = new JButton();
        alignLeftButton.setActionCommand("alignLeft");
        alignLeftButton.setToolTipText("Align left");
        alignLeftButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "alignLeft.png")));
        alignLeftButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(alignLeftButton);
        //align center
        JButton alignCenterButton = new JButton();
        alignCenterButton.setActionCommand("alignCenter");
        alignCenterButton.setToolTipText("Align center");
        alignCenterButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "alignCenter.png")));
        alignCenterButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(alignCenterButton);
        //align right
        JButton alignRightButton = new JButton();
        alignRightButton.setActionCommand("alignRight");
        alignRightButton.setToolTipText("Align right");
        alignRightButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "alignRight.png")));
        alignRightButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(alignRightButton);
        this.textToolBar.addSeparator();
        //section button
        JButton sectionButton = new JButton();
        sectionButton.setActionCommand("section");
        sectionButton.setToolTipText("Insert new section");
        sectionButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "section.png")));
        sectionButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(sectionButton);
        //numbered list button
        JButton enumButton = new JButton();
        enumButton.setActionCommand("enum");
        enumButton.setToolTipText("Insert new numbered list");
        enumButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "enum.png")));
        enumButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(enumButton);
        //bulleted list button
        JButton listButton = new JButton();
        listButton.setActionCommand("list");
        listButton.setToolTipText("Insert new bulleted list");
        listButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "list.png")));
        listButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(listButton);
        this.textToolBar.addSeparator();
        //column button
        JButton columnButton = new JButton();
        columnButton.setActionCommand("table_c");
        columnButton.setToolTipText("Insert new column");
        columnButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "table_c.png")));
        columnButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(columnButton);
        //table button
        JButton tableButton = new JButton();
        tableButton.setActionCommand("table_e");
        tableButton.setToolTipText("Insert new table");
        tableButton.setIcon(new ImageIcon(this.getClass().getResource(PATH + "table_e.png")));
        tableButton.setMargin(new Insets(0, 0, 0, 0));
        this.textToolBar.add(tableButton);

        for (Component tempTBItem : this.textToolBar.getComponents()) {
            if(tempTBItem instanceof JButton) {
                ((JButton) tempTBItem).addActionListener(actionListener);
                ((JButton) tempTBItem).setRolloverEnabled(false);
            }
        }

        /* Math Mode Toolbar */
        this.mathToolBar = new JToolBar();
        this.mathToolBar.setName("mathToolBar");
        this.mathToolBar.setFloatable(false);
        this.mathToolBar.setForeground(this.guiBackground);
        this.mathToolBar.setBackground(this.guiBackground);
        
        //square root
        JButton sqrtButton = new JButton();
        sqrtButton.setActionCommand("sqrt");
        sqrtButton.setToolTipText("Square root");
        sqrtButton.setIcon(new ImageIcon(getClass().getResource(PATH + "sqrt.png")));
        sqrtButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(sqrtButton);
        //fraction
        JButton fractionButton = new JButton();
        fractionButton.setActionCommand("frac");
        fractionButton.setToolTipText("Fraction");
        fractionButton.setIcon(new ImageIcon(getClass().getResource(PATH + "frac.png")));
        fractionButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(fractionButton);
        //limit
        JButton limitButton = new JButton(); //has bug in highlighting VARIABLE
        limitButton.setActionCommand("limit");
        limitButton.setToolTipText("Limit");
        limitButton.setIcon(new ImageIcon(getClass().getResource(PATH + "limit.png")));
        limitButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(limitButton);
        //summation
        JButton sumButton = new JButton();
        sumButton.setActionCommand("sum");
        sumButton.setToolTipText("Summation");
        sumButton.setIcon(new ImageIcon(getClass().getResource(PATH + "sum.png")));
        sumButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(sumButton);
        //integral
        JButton integralButton = new JButton();
        integralButton.setActionCommand("int");
        integralButton.setToolTipText("Integral");
        integralButton.setIcon(new ImageIcon(getClass().getResource(PATH + "integral.png")));
        integralButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(integralButton);
        //modular arithmetic
        JButton moduloButton = new JButton();
        moduloButton.setActionCommand("mod");
        moduloButton.setToolTipText("Modulo");
        moduloButton.setIcon(new ImageIcon(getClass().getResource(PATH + "mod.png")));
        moduloButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(moduloButton);
        //combination
        JButton combinationButton = new JButton();
        combinationButton.setActionCommand("binom");
        combinationButton.setToolTipText("Combination");
        combinationButton.setIcon(new ImageIcon(getClass().getResource(PATH + "comb.png")));
        combinationButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(combinationButton);
        this.mathToolBar.addSeparator();
        //math symbols
        JButton mathSymbolButton = new JButton();
        mathSymbolButton.setActionCommand("mathSymbol");
        mathSymbolButton.setToolTipText("Math symbols");
        mathSymbolButton.setIcon(new ImageIcon(getClass().getResource(PATH + "mathSymbol.png")));
        mathSymbolButton.setMargin(new Insets(0, 0, 0, 0));
        this.mathToolBar.add(mathSymbolButton);


        for (Component tempTBItem : this.mathToolBar.getComponents()) {
            if(tempTBItem instanceof JButton) {
                ((JButton) tempTBItem).addActionListener(actionListener);
                ((JButton) tempTBItem).setRolloverEnabled(false);
            }
        }

        //math toolbar is default
        this.toolBarPanel = new JTabbedPane(JTabbedPane.BOTTOM);
        this.toolBarPanel.insertTab("Math", null, this.mathToolBar, "Math functions", 0);
        this.toolBarPanel.insertTab("Text", null, this.textToolBar, "Text functions", 1);
        this.toolBarPanel.setForeground(this.guiTextColor);
        this.toolBarPanel.setBackground(this.guiBackground);
        this.toolBarPanel.addChangeListener(new CustomChangeListener(this.isDebug));
        this.north.add(this.toolBarPanel, BorderLayout.NORTH);
        /***********************************************************************
         * 
         **********************************************************************/

        //this panel is used to house the JLabels, TextFields, and the buttons
        //which will all be in separate panels of their own
        this.formulaMainPanel = new JPanel(new BorderLayout(1,1));
        this.formulaMainPanel.setBorder(BorderFactory.createEtchedBorder(5,
                this.background, this.guiForeground));

        JPanel formulaJLabelPanel = new JPanel(new BorderLayout(1,1));
        formulaJLabelPanel.setBackground(this.guiBackground);
        formulaJLabelPanel.add(new JLabel(" Latex Formulas: "), BorderLayout.NORTH);
        formulaJLabelPanel.getComponent(0).setForeground(this.guiTextColor);
        this.formulaMainPanel.add(formulaJLabelPanel, BorderLayout.WEST);

        /* Formula creation panel */
        JPanel formulaCreatorTextAndButtons = new JPanel(new BorderLayout(0, 0));
        JPanel formulaCreationPanel = new JPanel();
        formulaCreationPanel.setLayout(new BoxLayout(formulaCreationPanel, BoxLayout.X_AXIS));
        //formula field
        this.formulaField = new JTextField();
        this.formulaField.setForeground(this.foreground);
        this.formulaField.setBackground(this.background);
        this.formulaField.setCaretColor(this.guiTextColor);
        this.formulaField.addKeyListener(keyListener);
        this.formulaField.addCaretListener(new CustomCaretListener());
        formulaCreationPanel.add(this.formulaField, BorderLayout.CENTER);
        //enter button
        JButton enterButton = new JButton("Enter");
        enterButton.setRolloverEnabled(false);
        enterButton.addActionListener(actionListener);
        enterButton.setForeground(this.foreground);
        enterButton.setBackground(this.guiBackground);
        formulaCreationPanel.add(enterButton);
        //clear button
        JButton clearButton = new JButton("Clear");
        clearButton.setRolloverEnabled(false);
        clearButton.addActionListener(actionListener);
        clearButton.setBackground(this.guiBackground);
        clearButton.setForeground(this.foreground);
        clearButton.addActionListener(actionListener);
        formulaCreationPanel.add(clearButton);
        formulaCreatorTextAndButtons.add(formulaCreationPanel, BorderLayout.NORTH);
        this.formulaMainPanel.add(formulaCreatorTextAndButtons, BorderLayout.CENTER);
        this.formulaMainPanel.setVisible(true);

        this.north.add(this.formulaMainPanel, BorderLayout.SOUTH);
        this.add(this.north, BorderLayout.NORTH);

        /***********************************************************************
         *      latex code area
         **********************************************************************/
        this.center = new JPanel(new BorderLayout(1, 1));
        this.center.setBackground(this.guiBackground);

        //label
        JLabel codeLabel = new JLabel(" LaTeX Area");
        codeLabel.setForeground(this.guiTextColor);
        this.center.add(codeLabel, BorderLayout.NORTH);

        //code area
        this.latexCodeArea.setText(BOILERPLATE);
        this.latexCodeArea.setCaretPosition(this.latexCodeArea.getText().indexOf("}") + 1);
        /*
         * We need to create a completely new caret listener if we are to go
         * that route...the one thats set up right now is built for the
         * forumla area
         */
        //this.latexCodeArea.addCaretListener(new CustomCaretListener());
        this.latexCodeArea.setBorder(BorderFactory.createEtchedBorder(5, this.guiForeground,
                this.background));
        this.latexCodeArea.setForeground(this.foreground);
        this.latexCodeArea.setBackground(this.background);
        this.latexCodeArea.setLineWrap(true);
        JScrollPane latexCodeScrollPane = new JScrollPane(this.latexCodeArea);
        this.center.add(latexCodeScrollPane, BorderLayout.CENTER);

        JPanel southCompilerWindowPanel = new JPanel(new BorderLayout(1,1));
        southCompilerWindowPanel.setBackground(this.guiBackground);
        southCompilerWindowPanel.add(new JLabel(" Compiler Message Area:"), BorderLayout.CENTER);
        ((JLabel) southCompilerWindowPanel.getComponent(0)).setForeground(this.guiTextColor);

        JPanel compilerAreaButtonPanel = new JPanel(new BorderLayout(1, 1));
        this.showHideCompileAreaButton = new JButton("Show Compiler Return Area");
        compilerAreaButtonPanel.add(this.showHideCompileAreaButton, BorderLayout.WEST);
        compilerAreaButtonPanel.getComponent(0).setForeground(this.foreground);
        compilerAreaButtonPanel.getComponent(0).setBackground(this.guiBackground);
        ((JButton) compilerAreaButtonPanel.getComponent(0)).addActionListener(actionListener);
        ((JButton) compilerAreaButtonPanel.getComponent(0)).setRolloverEnabled(false);
        compilerAreaButtonPanel.add(new JButton("Preview LaTeX Document"), BorderLayout.EAST);
        compilerAreaButtonPanel.getComponent(1).setForeground(this.foreground);
        compilerAreaButtonPanel.getComponent(1).setBackground(this.guiBackground);
        ((JButton) compilerAreaButtonPanel.getComponent(1)).setActionCommand("Preview");
        ((JButton) compilerAreaButtonPanel.getComponent(1)).addActionListener(actionListener);
        ((JButton) compilerAreaButtonPanel.getComponent(1)).setRolloverEnabled(false);
        compilerAreaButtonPanel.setBackground(this.guiBackground);
        southCompilerWindowPanel.add(compilerAreaButtonPanel, BorderLayout.EAST);
        this.center.add(southCompilerWindowPanel, BorderLayout.SOUTH);

        this.add(this.center, BorderLayout.CENTER);
        /***********************************************************************
         *
         **********************************************************************/

        //compiler textArea
        this.compilerReturnArea = new JTextArea();
        this.compilerReturnArea.setPreferredSize(new Dimension(this.getWidth(), 150));
        this.compilerReturnArea.setEditable(false);
        this.compilerReturnArea.setLineWrap(true);
        this.compilerReturnArea.setForeground(this.guiTextColor);
        this.compilerReturnArea.setBackground(this.guiBackground);
        this.south = new JScrollPane(this.compilerReturnArea);
        this.south.setPreferredSize(new Dimension(this.getWidth(), 150));
        this.south.setVisible(false);
        this.add(this.south, BorderLayout.SOUTH);

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setPreferredSize(new Dimension(900, 800));
        this.setVisible(true);
        this.initialize = false;

        pack();
    }

    //need to add equation boiler plate code: \\begin{equation}\nCODE\n\\end{equation}
    /**
     * 
     */
    protected void copyFromFormulaBarToMainArea() {
        /*
         * if the cursor is at the end of the latexCodeArea text, and
         * the latexCodeArea is not empty, then add a new line to
         * separate the new formula that we are adding from the stuff
         * we had in there before
         */
        //get the cursor position to reset it later
        int oldCarotLoc = this.latexCodeArea.getCaretPosition();
        //assemble the text to insert, so that way we can measure it's length
        String textToInsert = "\\begin{equation}\n" + "\t" + this.formulaField.getText()
                + "\n\\end{equation}\n";
        int latexCodeAreaLength = textToInsert.length();

        String latexAreaText = this.latexCodeArea.getText();

        this.latexCodeArea.setText(latexAreaText.substring(0, this.latexCodeArea
                .getCaretPosition()) + textToInsert + latexAreaText.substring(this.latexCodeArea
                .getCaretPosition()));
        //reset cursor location
        this.latexCodeArea.setCaretPosition(oldCarotLoc + latexCodeAreaLength);
        
        this.formulaField.setText("");
    }

    protected void iterateThroughContainer(Container c) {
        if(c instanceof GUI){
            iterateThroughContainer(this.fileChooser);
            iterateThroughContainer(this.optionsFrame);
        }
        Component [] thingsToIterate = null;
        c.setBackground(background);
        c.setForeground(foreground);

        if(c instanceof JMenu){
            thingsToIterate = ((JMenu)c).getMenuComponents();
        } else {
            thingsToIterate = c.getComponents();
        }
        for (Component temp : thingsToIterate) {
            if(this.isDebug)
                System.out.println(temp.getClass());
            
            temp.setForeground(this.foreground);
            temp.setBackground(this.guiBackground);

            if(temp instanceof Container){
                iterateThroughContainer((Container)temp);
            }
            if(temp instanceof JMenuItem && this.initialize){
                ((JMenuItem)temp).addActionListener(this.actionListener);
            }
        }
    }

    protected void setTextAreasColor(){
            Color newBackground = new Color(Math.abs(background.getRed()
                    - 50), Math.abs(background.getGreen() - 50), Math.abs(
                    background.getBlue() - 50));
            compilerReturnArea.setBackground(newBackground);
            latexCodeArea.setBackground(newBackground);
            formulaField.setBackground(newBackground);

            if(isDebug)
                System.out.println("Old Fore: " + (foreground.getRed())+ " " +
                        (foreground.getGreen())+ " " + (
                        foreground.getBlue()));

            Color newForeground = new Color(((foreground.getRed()
                    + 50) > 255)?255:(foreground.getRed()+ 50), ((foreground.
                    getGreen() + 50)> 255)? 255:(foreground.getGreen() + 50),
                    ((foreground.getBlue() + 50) > 255)? 255:(foreground.getBlue() + 50));

            if(isDebug)
                System.out.println("new Fore: " + (newForeground.getRed())+ " " +
                        (newForeground.getGreen())+ " " +(
                        newForeground.getBlue()));

            compilerReturnArea.setForeground(newForeground);
            latexCodeArea.setForeground(newForeground);
            formulaField.setForeground(newForeground);
    }
}
